#!/bin/bash


__FileName__=""
__Author__="ShiWei"
__Time__="/2021/06/20"
__Version__="V3.9"




version () {
	# shellcheck disable=SC2059
	printf "\033[34m
=============================================================
*   ${PROGRAM_NAME} ${PROGRAM_VERSION}
*   ${AUTHOR_NAME}          ${AUTHOR_NUMBER}
=============================================================
Release Note:
    >>V1.0 20210620 is first commit
    >>V1.2.1 20210927
    1. Fixed Check device is empty of '/proc/net/dev'
    >>V1.5.3 20210105
    1. Add Bonding of parameters:  BONDING_OPTS
    >>V1.8.2 20220410
    1. Modify Check Connection and Device of name is not same as Question
    >>V2.0 20221018
    1. Add Adaptation RHEL9.0
    2. Add Check Bond Slave of GENERAL.TYPE, is must be ethernet
    3. Add Adaptation NetworkManager Plugins of keyfile or ifcfg-rh
    4. Modify Color Output
    >>V2.6 20221019
    1. Modidy Text Output of success or failure
    2. Replace Chinese Output with English Output
    3. Fixed Check whether the Bond Network port exists
    4. Fixed Absolutely delete Bond Network
    >>V2.7 20230608
    1. Add Adaptation Kylin Linux Advanced Server V10
    2. Modify View the config File of the Slave interface
    >>V3.0 20230626
    >>V3.3 20230825
    1. Modify funtion: check_this_os
    2. Add argument: Os_Serial_Type_Name
    >>V3.5 20230827
    1. Add Adaptation Ubuntu 22.04 LTS\
    2. Add Funtion: jedge_net_mgmt
    >>V3.6 20240821
    1. Add Adaptation openEuler 22.03 LTS
    >>V3.7 20250529
    1. Add Adaptation anolis 8.9/23.02
    >>V3.8 20250530
    1. Add Adaptation UOS v20
    >>V3.9 20250830
    1. Add Adaptation BcLinux\
---------------------------------------------------------------
    \033[0m\n"
	exit 0
}

author () {
	printf "$AUTHOR_NAME $AUTHOR_NUMBER \n"
	exit 0
}


functions_env () {
    umask 022
    [ -z "${COLUMNS:-}" ] && COLUMNS=80
    if [ -z "${BOOTUP:-}" ]; then
        BOOTUP=color
        RES_COL=60
        MOVE_TO_COL="echo -en \\033[${RES_COL}G"
        SETCOLOR_SUCCESS="echo -en \\033[1;32m"
        SETCOLOR_FAILURE="echo -en \\033[1;31m"
        SETCOLOR_WARNING="echo -en \\033[1;33m"
        SETCOLOR_INSTALLING="echo -en \\033[1;35m"
        SETCOLOR_NORMAL="echo -en \\033[0;39m"
        LOGLEVEL=1
        if LANG=C tty | grep --quiet -e '\(/dev/ttyS\|not a tty\)'; then
            BOOTUP=serial
            MOVE_TO_COL=
            SETCOLOR_SUCCESS=
            SETCOLOR_FAILURE=
            SETCOLOR_WARNING=
            SETCOLOR_NORMAL=
        fi
    fi
}
echo_success() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
    echo -n $"  OK  "
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 0
}
echo_failure() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo -n $"FAILED"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}
echo_warning() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo -n $"WARNING"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}
success() {
    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success
    return 0
}
failure() {
    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure
    return 1
}

warning() {
    local rc=$?
    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_warning
    return $rc
}
action() {
    local STRING rc
    STRING=$1
    echo -n "$STRING "
    shift
    "$@" && success $"$STRING" || failure $"$STRING"
    rc=$?
    echo
    return $rc
}
strstr() {
    [ "${1#*$2*}" = "$1" ] && return 1
    return 0
}



rand() {
:<<!
随机函数 [2,250]
!
    min=2
    max=$((251-$min+1))
    num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}')
    echo $(($num%$max+$min))
}

judge_res() {
:<<!
para 1: 存在状态; 0: 存在
para 2: 判断方向; 0: 不希望存在
para 3: 网口名
para 4: 网络设备类型
!
    if [ "${2}" == "0" ]; then
        if [ "${1}" == "0" ]; then
            error "Sorry! ${4} Adapter 【${3}】 is already exists....."
        fi
    elif [ "${2}" == "1" ]; then
        if [ "${1}" !=  "0" ];then
            error "Sorry! ${4} Adapter 【${3}】 not exists....."
        fi
    fi
}

judge_port () {
:<<!
para 1: 网口名
para 2: 0: 不希望存在； 1: 希望存在
para 3: 网络设备类型， ethernet , bond
!
    panduan_res=""
    panduan_type="${3}"
    if [[ "${panduan_type}" == "" || "${panduan_type}" == "bond" ]]; then
        [[ "${panduan_type}" == "" ]] && panduan_type="ethernet"
        cat /proc/net/dev | sed '3,$p' -n | egrep -iv 'lo|^virbr|vnet|face|inter' | awk '{print $1}' | sed 's/.$//' | egrep "^${1}$" &> /dev/zero
        if [ $? -eq 0 ]; then
            [[ "`nmcli -f GENERAL.TYPE device show ${1} | awk '{print $NF}' | xargs`" = "${panduan_type}" ]] && panduan_res=0 || panduan_res=1
        else
            panduan_res=1
        fi
    elif [[ "${panduan_type}" == "vir" ]]; then
        panduan_type="vlan|bridge|tun"
        cat /proc/net/dev | sed '3,$p' -n | egrep -iv 'lo|^virbr|vnet|face|inter' | awk '{print $1}' | sed 's/.$//' | egrep "^${1}$" &> /dev/zero
        if [ $? -eq 0 ]; then
            [[ "${panduan_type}" =~ "`nmcli -f GENERAL.TYPE device show ${1} | awk '{print $NF}' | xargs`" ]] && panduan_res=0 || panduan_res=1
        else
            panduan_res=1
        fi
        nmcli connection | sed '2,$p' -n | awk '{print $1}'  | egrep "^${1}$" &> /dev/zero
        panduan_res=$?
    fi
    judge_res ${panduan_res} ${2} ${1} ${panduan_type}
}

parse_vir_interface () {
    j=0
    if [[ "${NetworkManager_plugins}" = "ifcfg-rh" ]]; then
        bond_master_file_name="/etc/sysconfig/network-scripts/ifcfg-${bond_name}"
        for i in `find /etc/sysconfig/network-scripts  -type f  -name "ifcfg-bond-slave-*"`
        do
            father=`cat $i | egrep "^MASTER=" | awk -F'=' '{print $2}'`
            slave_file_name=`basename $i`
            bond_slave_name=`cat $i | egrep "^NAME=" | awk -F'=' '{print $2}'`
            phy_bond_slave_name=`cat $i | egrep "^DEVICE=" | awk -F'=' '{print $2}'`
            if [[ "${father}" == "${1}" ]];then
                vir_interface_arr[${j}]=${bond_slave_name}
                phy_interface_arr[${j}]=${phy_bond_slave_name}
                bond_slave_file_arr[${j}]="/etc/sysconfig/network-scripts/ifcfg-${bond_slave_name}"
                let j++
            fi
        done
    else
         bond_master_file_name="/etc/NetworkManager/system-connections/${bond_name}.nmconnection"
        for i in `find /etc/NetworkManager/system-connections  -type f  -name "bond-slave-*.nmconnection"`
        do
            father=`cat $i | egrep "^master=" | awk -F'=' '{print $2}' | xargs`
            slave_file_name=`basename $i`
            bond_slave_name=`cat $i | egrep "^id=" | awk -F'=' '{print $2}' | xargs`
            phy_bond_slave_name=`cat $i | egrep "^interface-name=" | awk -F'=' '{print $2}' | xargs`
            if [[ "${father}" == "${1}" ]];then
                vir_interface_arr[${j}]=${bond_slave_name}
                phy_interface_arr[${j}]=${phy_bond_slave_name}
                bond_slave_file_arr[${j}]="/etc/NetworkManager/system-connections/${bond_slave_name}.nmconnection"
                let j++
            fi
        done
    fi
}

optim_net_card () {
    ip link set ${1// /} mtu 9000
    nmcli c modify ${1} autoconnect yes
    sleep 1
    combined=`ethtool  -l  ${1} | grep "Combined" | head -1 | awk -F ":" '{print $2}' | xargs`
    ethtool -L ${1} combined  ${combined// /}
    sleep 1
    rx_num=`ethtool -g ${1} | grep -i rx:  | sed -n  '1p' | cut -d: -f2`
    tx_num=`ethtool -g ${1} | grep -i tx:  | sed -n  '1p' | cut -d: -f2`
    ethtool -G ${1} rx  ${rx_num// /}  tx  ${tx_num// }
    ip link set ${1// /} up
    nmcli c up ${1// /}
    sleep 1
} &> /dev/zero

judge_port_is_connect () {
    dev_state=$(ip addr show $1  | sed '1p' -n  | awk -F state '{print $2}' | awk '{print $1}')
    if [ "${dev_state}" != "UP" ]; then
        echo 0 ; return 1
    else
        echo 1 ; return 1
    fi
}

judge_numcli () {
    if [ "${Os_Serial_Type_Name}" == "rhel" ]; then
        rpm -qa | egrep 'NetworkManager-[0-9].*' &> /dev/zero
        if [ $? -ne 0 ]; then
            error "NetworkManager Software package does not exist..... "
        fi
    elif [ "${Os_Serial_Type_Name}" == "debian" ]; then
        if ! `dpkg -l network-manager &> /dev/null `; then error "network-manager Software package does not exist..... " ; fi
    fi
    systemctl status NetworkManager &> /dev/zero
    if [ $? -ne 0 ]; then
        systemctl start NetworkManager
        if [ $? -ne 0 ]; then
            systemctl status NetworkManager
            error "NetworkManager Unable to Start-Up, Please Check it Out......"
        fi
    fi
    NetworkManager -V &> /dev/zero || error "bash: NetworkManager: command not found..."
    nmcli -v &> /dev/zero || error "bash: nmcli: command not found..."
}

judge_net_mgmt () {
    if [ "${Os_Serial_Type_Name}" == "rhel" ]; then
        if [[ ${version_id_first} -ge 9 ]]; then
            plugins_str=$(NetworkManager --print-config | egrep '^plugins=')
            if [ -z "${plugins_str}" ]; then
                NetworkManager_plugins="keyfile"
            else
                NetworkManager_plugins=$(echo "${plugins_str}" | awk -F'=' '{print $2}' | cut -d, -f1 | xargs)
            fi
        fi
    elif [ "${Os_Serial_Type_Name}" == "debian" ]; then
        if [ $Version_Id_First -ge 22 ]; then
            network_process=$(netplan get renderer 2> /dev/null)
            if [ ! "${network_process}" == "NetworkManager" ]; then
                error "The current system daemon for network device management is not NetworkManager"
            fi
            plugins_str=$(NetworkManager --print-config | egrep '^plugins=')
            if [ -n "${plugins_str}" ]; then
                NetworkManager_plugins="keyfile"
            else
                NetworkManager_plugins=$(echo "${plugins_str}" | awk -F'=' '{print $2}' | cut -d, -f1 | xargs)
            fi
            if ! `nmcli -f STATE g status | sed '1d;p' -n | xargs | egrep '^connected' -q ` ; then  error "NetworkManager is not connected" ; fi
        fi
    fi
}

clear_other_connection () {
:<<!
para 1 : 设备名
para 2 : all: 删除所有链接
!
    if [[ "${NetworkManager_plugins}" = "ifcfg-rh" ]]; then
        all_device=($(find /etc/sysconfig/network-scripts/ -type f -name 'ifcfg-*'))
        for fff in ${all_device[@]}; do
            device=$(cat "${fff}" | egrep "^DEVICE=" | awk -F'=' '{print $2}' | xargs)
            name=$(cat "${fff}" | egrep "^NAME=" | awk -F'=' '{print $2}' | xargs)
            dev_master=$(cat "${fff}" | egrep "^MASTER=" | awk -F'=' '{print $2}' | xargs)
            if [[ -z "${device}" || -z "${name}" ]]; then
                rm -rf "${fff}"
                continue
            fi
            if [ -n "${dev_master}" ]; then
                for ddd in ${interface_arr[@]}; do
                    if [[ "${ddd}" == "${device}" && "${ddd}" != "${name}" ]]; then
                        nmcli connection del ${name}
                        if [ $? -ne 0 ]; then
                            rm -rf "${fff}"
                        fi
                    fi
                done
            fi
        done
    else
        all_device=($(find /etc/NetworkManager/system-connections -type f -name '*.nmconnection'))
         for fff in ${all_device[@]}; do
            interface_name=$(cat "${fff}" | egrep "^interface-name=" | awk -F'=' '{print $2}' | xargs)
            id_name=$(cat "${fff}" | egrep "^id=" | awk -F'=' '{print $2}' | xargs)
            dev_master=$(cat "${fff}" | egrep "^master=" | awk -F'=' '{print $2}' | xargs)
            if [[ -z "${device}" || -z "${name}" ]]; then
                rm -rf "${fff}"
                continue
            fi
            if [ -n "${dev_master}" ]; then
                for ddd in ${interface_arr[@]}; do
                    if [[ "${ddd}" == "${device}" && "${ddd}" != "${name}" ]]; then
                        nmcli connection del ${name}
                        if [ $? -ne 0 ]; then
                            rm -rf "${fff}"
                        fi
                    fi
                done
            fi
         done
    fi
}

reset_device () {
    ip_addresses="$(rand).$(rand).$(rand).$(rand)/24"
    nmcli connection add type ethernet con-name ${1} ifname ${1} autoconnect yes ipv4.method manual ipv4.addresses ${ip_addresses}
    return $?
}

judge_config_file () {
:<<!
para 1: dev 名
para 2: connection 名
para 3: dev 类型
!
    if [[ "${1}" != "${2}" ]]; then
        nmcli connection delete "${2}"
        nmcli connection delete "${1}" &> /dev/null
        reset_device "${1}" && return
    fi
    if [[ "${NetworkManager_plugins}" = "ifcfg-rh" ]]; then
        eth_config_file="/etc/sysconfig/network-scripts/ifcfg-${1}"
    else
        eth_config_file="/etc/NetworkManager/system-connections/${1}.nmconnection"
    fi
    if [[ ! -f "${eth_config_file}" ]]; then
        nmcli connection delete "${2}"
        reset_device "${1}" && return
    fi
    connection_ipv4_method=$(nmcli -f ipv4.method connection show "${2}" | awk '{print $NF}' | xargs)
    if [[ "${connection_ipv4_method}" != "manual" ]]; then
        nmcli connection modify "${2}" ipv4.method manual
    fi
    wait
    connection_ipv4_address=($(nmcli -f ip4.address connection show "${2}" | awk '{print $NF}' | xargs))
    if [[ ${#connection_ipv4_address[@]} -ne 0 ]]; then
         ip_addresses="$(rand).$(rand).$(rand).$(rand)/24"
         nmcli connection modify ${1} ipv4.method manual ipv4.addresses ${ip_addresses}
     fi
     nmcli connection modify ${1} autoconnect yes
}

connected_deal () {
:<<!
para 1: 网口名
para 2: 活动的 connection 名
!
    judge_config_file "$@"
}

connection_deal () {
:<<!
para 1: 网口名
para 2: 活动的 connection 名
!
    judge_config_file "$@"
}

disconnected_deal () {
    nmcli connection delete ${1} &> /dev/null
    reset_device "${1}"
}

judge_con_name_valid () {
:<<!
para 1: 设备名
!
    dev_is_up=$(judge_port_is_connect ${dev})
    ifname_text=$(nmcli -f DEVICE,TYPE,STATE,CONNECTION -t device | awk -F':' -v ddd=$1 '{if ($1 == ddd) print $0; }' | sed '1p' -n)
    if [ -n "${ifname_text}" ]; then
        ifname_type=$(echo ${ifname_text} | awk -F':' '{print $2}' | xargs)
        ifname_stateing=$(echo ${ifname_text} | awk -F':' '{print $3}' | xargs)
        active_conn=$(echo ${ifname_text} | awk -F':' '{print $NF}' | xargs)
        echo ${bond_phy_general_types[@]} | grep "${ifname_type}" --quiet
        [[ $? -ne 0 ]] && error "*** Device ${1} of the GENERAL.TYPE: ${ifname_type} ; is invalid...."
        case "${ifname_stateing}" in
            connected)     ifname_state=1 ; connected_deal "$1" "${active_conn}" "${ifname_type}" ; ;;
            connection)    ifname_state=2 ; connection_deal "$1" "${active_conn}" "${ifname_type}" ; ;;
            disconnected)  ifname_state=3 ; disconnected_deal "$1" "${active_conn}" "${ifname_type}" ; ;;
            connected\ \(externally\))   ifname_state=4 ; connected_deal "$1" "${active_conn}" "${ifname_type}" ; ;;
            unavailable)   ifname_state=5 ; disconnected_deal "$1" "${active_conn}" "${ifname_type}" ;;
            connecting\ \(getting\ IP\ configuration\)) ifname_state=6 ; connection_deal "$1" "${active_conn}" "${ifname_type}" ; ;;
            unmanaged)     ifname_state=7 ; error "*** Device ${1} of the GENERAL.STATE: ${ifname_stateing} ; is invalid...." ; ;;
        esac
    else
        error "*** Device ${1} is invalid! Please Check it Out....." ;
    fi
    wait
}

reset_NetworkManager () {
    for son in ${interface_arr[@]}
    do
        ip addr flush ${son}
        ifconfig ${son} 0
        nmcli device reapply ${son} &> /dev/zero
        nmcli connection reload ${son}
        sleep 1
    done
    systemctl restart NetworkManager &> /dev/zero
    sleep 1
}

bonding_custom_config () {
:<<!
para 1: bond ID
!
    case "${1}" in
        "0") BONDING_OPTS="mode=0 miimon=100 updelay=200" ; ;;
        "1") BONDING_OPTS="mode=1 miimon=100 updelay=200" ; ;;
        "2") BONDING_OPTS="mode=2 miimon=100 updelay=200 xmit_hash_policy=layer3+4" ; ;;
        "3") BONDING_OPTS="mode=3 miimon=100 updelay=200 xmit_hash_policy=layer2" ; ;;
        "4") BONDING_OPTS="mode=4 miimon=100 updelay=200 xmit_hash_policy=layer3+4" ; ;;
        "5") BONDING_OPTS="mode=5 miimon=100 updelay=200 xmit_hash_policy=2" ;  ;;
        "6") BONDING_OPTS="mode=6 miimon=100 updelay=200 xmit_hash_policy=2" ;  ;;
    esac
    if [[ "${NetworkManager_plugins}" = "ifcfg-rh" ]]; then
        echo "BONDING_OPTS=\"${BONDING_OPTS}\"" >> /etc/sysconfig/network-scripts/ifcfg-${bond_name}
    else
        nmcli c modify ${bond_name} bond.options "${BONDING_OPTS// /,}"
    fi
}

bonding_reset () {
    systemctl restart NetworkManager.service
    sleep 2
} &> /dev/zero

bonding_ROOT () {
:<<!
############## 主程序  ##############
!
    case "${operate_type}" in
        add_bond)    judge_port ${bond_name} "0" "bond" ; add_bonding; ;;
        del_bond)    judge_port ${bond_name} "1" "bond" ; del_bonding; ;;
        update_bond) judge_port ${bond_name} "1" "bond" ; update_bonding "down"; update_bonding "up"; ;;
    esac
    if [ $info_option -eq 1 ]; then
        judge_port ${bond_name} 1 "bond"
        info_bonding
    fi
}

add_bonding () {
    printf "\033[33m\n   ************* Create ${bond_name}[mode=${type_num}] ************* \033[0m\n"
    clear_other_connection
    sleep 1
    mode_li=("balance-rr" "active-backup" "balance-xor" "broadcast" "802.3ad" "balance-tlb" "balance-alb")
    ip_addresses="$(rand).$(rand).$(rand).$(rand)/24"
    nmcli connection add type bond con-name  ${bond_name}  ifname  ${bond_name}  mode  ${mode_li[${type_num}]} autoconnect yes ipv4.method manual ipv4.addresses ${ip_addresses}
    wait
    for son in ${interface_arr[@]}
    do
        nmcli connection add type bond-slave ifname  ${son}  master  ${bond_name} autoconnect yes
        sleep 1
    done
    sleep 2
    bonding_custom_config ${type_num}
    update_bonding  down
    wait; sync
    sleep 3
    update_bonding  up
}

del_bonding () {
    printf "\033[33m   ************* Delete ${bond_name} ************* \033[0m\n"
    nmcli connection delete $bond_name &> /dev/zero
    if [ $? -eq 0 ];then
        success && echo "nmcli c delete $bond_name"
    else
        failure || error "Port: $bond_name delete failure"
    fi
    parse_vir_interface ${bond_name}
    for dev in ${vir_interface_arr[@]}
    do
        nmcli connection delete $dev &> /dev/zero
        if [ $? == 0 ];then
            success && echo "nmcli c delete $dev"
        else
            failure || echo "Slave Interface 【$dev】Existence"
        fi
        wait
    done
    remain_devi=($(nmcli -f DEVICE -t device  | egrep "^${bond_name}$" | xargs))
    if [ -n "${remain_devi[@]}" ]; then
        for fff in ${remain_devi[@]}; do nmcli device delete ${fff}; done &> /dev/null
    fi
    bonding_reset
}

update_bonding () {
    printf "\033[33m   ************* Update ${bond_name}[${1}] ************* \033[0m\n"
    if [ "${1}" == "up" ]; then
        eval "nmcli connection ${1} ${bond_name}" &> /dev/zero
        if [ $? -eq 0 ];then
            success && echo "nmcli c ${1} ${bond_name}"
        else
            failure || error "Port: ${bond_name} ${1} failure"
        fi
        ip link set ${bond_name} mtu 9000 up
        parse_vir_interface ${bond_name}
        for dev in ${vir_interface_arr[@]}
        do
            eval "nmcli connection ${1} ${dev}" &> /dev/zero
            if [ $? == 0 ];then
                success && echo "nmcli c ${1} ${dev}"
            else
                failure || echo "Slave Interface ${dev} Existence"
            fi
            wait
            sleep 1
        done
    fi
    if [ "${1}" == "down" ]; then
        eval "nmcli connection ${1} ${bond_name}" &> /dev/zero
        if [ $? -eq 0 ];then
            success && echo "nmcli c ${1} ${bond_name}"
        else
            failure || error "Port: ${bond_name} ${1} failure"
        fi
    fi
    bonding_reset
}

info_bonding () {
    printf "\033[33m   ************* Query ${bond_name} ************* \033[0m\n"

    parse_vir_interface ${bond_name}
    printf "\n\033[35m***************** ${bond_name} Network Info:\033[0m\n"
    ip -s addr show ${bond_name}
    for dev in ${phy_interface_arr[@]}
    do
        printf "\n\033[35m***************** ${bond_name} Physical Slave ${dev} Status Info:\033[0m\n"
        ip -s addr show ${dev}
        printf "\n\033[35m***************** ${bond_name} Physical Slave ${dev} Ethtool Info:\033[0m\n"
        ethtool ${dev}
        echo
        ethtool -i ${dev}
    done
    printf "\n\033[35m***************** ${bond_name} Config File Info:\033[0m\n"
    cat "${bond_master_file_name}"
    for file_id in `seq 0 $((${#phy_interface_arr[@]} - 1))`
    do
        printf "\n\033[35m***************** ${bond_name} Bonding Slave ${vir_interface_arr[file_id]} Config File Info:\033[0m\n"
        cat "${bond_slave_file_arr[file_id]}"
    done
    printf "\n\033[35m***************** Bonding Master: ${bond_name}: /proc/net/bonding/${bond_name}:\033[0m\n"
    cat /proc/net/bonding/${bond_name}
    printf "\n\033[35m***************** Bonding Master: ${bond_name} Ethtool Info:\033[0m\n"
    ethtool ${bond_name}
    ethtool -i ${bond_name}
}



error () {
	printf "\033[31m[$date_time]\033[36m $PROGRAM_NAME run with error at:\033[31m $@\033[0m\n"
	exit 1
}

debug_log () {
    dangqian_time=`date +%Y.%m.%d.%H.%M.%S`
}

check_user_is_root () {
    username=$(whoami)
    if [ "$username" != "root" ]
    then
        error  "Username is must be root"
        exit 1
    fi
}

check_this_os () {
    export CPU_MODEL_NAME=`lscpu | awk -F':' '/Model name/{print $2}' | tr A-Z a-z | xargs`
    if [ -s "/etc/redhat-release" ]; then
        export Os_Type=`cat /etc/os-release | awk -F'=' '/^ID=/{print $2}' | xargs`
        export Os_Version=`cat /etc/os-release | awk -F'=' '/^VERSION_ID=/{print $2}' | xargs`
        export Version_Id_First=`echo ${Os_Version} | cut -d '.' -f1`

    elif [ -s "/etc/centos-release" ]; then
        export Os_Type=`cat /etc/centos-release | grep -i centos | awk '{print $1}' | tr A-Z a-z | xargs`
        export Os_Version=`cat /etc/centos-release | grep -i centos | awk '{print $3}' | tr A-Z a-z | xargs`
        export Version_Id_First=`echo ${Os_Version} | cut -d '.' -f1`
    elif [ -s "/etc/os-release" ]; then
        export Os_Type=`cat /etc/os-release | awk -F'=' '/^ID=/{print $2}' | xargs`
        export Os_Version=`cat /etc/os-release | awk -F'=' '/^VERSION_ID=/{print $2}' | xargs`
        export Version_Id_First=`echo ${Os_Version} | cut -d '.' -f1`
    elif [ -s "" ]; then
        echo
    else
        echo
        exit 1
    fi
    Architecture=`uname -m`  # x86_64
    rhel_serial_system=("rhel" "kylin" "rocky" "centos" "ctyunos" "openEuler" "anolis" "uos" "bclinux")
    debian_serial_system=("ubuntu" "debian" )
    for os_name in "${rhel_serial_system[@]}"; do
        if [[ "$(echo "${Os_Type}" | grep -ic "${os_name}")" -ne 0 ]]; then
            Os_Serial_Type_Name="rhel" ; return 0
        fi
    done
    for os_name in "${debian_serial_system[@]}"; do
        if [[ "$(echo "${Os_Type}" | grep -ic "${os_name}")" -ne 0 ]]; then
            Os_Serial_Type_Name="debian" ; return 0
        fi
    done
    echo "unknown serial system"
    exit 1
}

config_envir () {
    export LANG="en_US-UTF-8"
    functions_env
    check_this_os
}

clean_envir () {
    echo

}

usage_and_exit () {
    echo
    printf "${PROGRAM_NAME} Version ${PROGRAM_VERSION}\n"
	printf "\\033[32m
   Bonding 自动化脚本
Usage:
  $PROGRAM_NAME <-a|-d|-u> [-i] [-l] [-t] [物理网口名]
Options:
    -a, --add      添加 bonding 网口
    -t, --type     bonding 种类, [0-6]
    -d, --delete   删除 bonding 网口
    -r, --remove   根据物理网口名删除 Bonding
    -u, --update   更新 bonding 网口
    -i, --info     查看 bonding 网口信息
    -l, --log      日志输出文件名, DF: ${default_log_file}
    -v, --version  show $PROGRAM_NAME versions
    --author       show author name
    -h, --help     show help message
    -q 退出——for quit the Script
    -? show this list\n\
Examples:
    ${PROGRAM_NAME} -a <Bond name> -t <0-6> xxx xxx
    ${PROGRAM_NAME} -d <Bond name> 
    ${PROGRAM_NAME} -i <Bond name> 
    ${PROGRAM_NAME} -a <Bond name> -t <0-6> xxx xxx -lxxxxx.log
    ${PROGRAM_NAME} -i <Bond name>  --log=xxxxx.log\033[0m
"
}


date_time=`date +%Y.%m.%d.%H.%M.%S`
PROGRAM_NAME=$(basename $0)
PROGRAM_VERSION="V3.9"
AUTHOR_NAME="ShiWei"
AUTHOR_NUMBER="50023"
BASE_DIR="`pwd`"
Os_Type=""
Os_Version=""
Version_Id_First=""
Architecture=""
Os_Serial_Type_Name=""
NetworkManager_plugins="ifcfg-rh"
port_option=0
port_name=""
default_log_file="${PROGRAM_NAME%.sh*}_all_log_${date_time}"
log_opt=0
log_file_name=$default_log_file
quit_option=0
add_option=0
bond_name=""
del_option=0
update_option=0
info_option=0
type_option=0
type_num=""

remove_option=0

operate_type=""

declare -a interface_arr
declare -a vir_interface_arr
declare -a phy_interface_arr
declare -a bond_slave_file_arr
bond_master_file_name=""
declare -a bond_phy_general_types=("ethernet")




panda () {
    if [[ "$1" == "''" ]];then
        echo ""
    else
        echo `echo $1 | xargs`
    fi
}

judge_correct () {
    tmp_result=$(($add_option+$del_option+$update_option))
    if [ $tmp_result -gt 1 ]; then
        error "option -a -d -u is only one allow and must be exists one option"
    fi
    tmp_result_02=$(($del_option+$remove_option))
    if [ $tmp_result_02 -gt 1 ]; then
        error "option -d -r is only one allow and must be exists one option"
    fi
    judge_numcli
    judge_net_mgmt
    if [ $add_option -eq 1 ]; then
        if [ $type_option -ne 1 ]; then
            error "The -a argument,  must be exists -t option"
        fi
        if [[ ! "${type_num}" =~ ^[0-6]{1}$ ]]; then error "The -t argument is Invalid parameter value:[0-6]"; fi
        if [ ${#interface_arr[@]} -lt 2 ]; then
            error "interface num must be greater than or equal to 2"
        fi
        local after_inter_list=(`echo ${interface_arr[@]} | xargs | sed 's/ /\n/g' | sort | uniq`)
        if [[ "${#interface_arr[@]}" != "${#after_inter_list[@]}" ]]; then
            failure || printf "\033[31mSlave repetitive: %s\033[0m\n" "${interface_arr[*]}"; exit 1
        else
            success && printf "\033[34mSlave repetitive: %s\033[0m\n" "${interface_arr[*]}"
        fi
        judge_port ${bond_name} 0 "bond"
        for dev in ${interface_arr[@]}; do
            judge_port ${dev} 1
            judge_con_name_valid ${dev}
        done
        modprobe bonding
        if [ $? -ne 0 ]; then error "module bonding is not exists ..... "; fi
    fi
}

arg_parse () {
    getopt -T &>/dev/null ;[ $? -ne 4 ] && { echo "not enhanced version";exit 1; }
    set -- $(getopt -o a:t:d:ru:i:l::vhq --long add:,type:,delete:,remove,update:,info:,log::,version,author,help -n "$0" -- "$@")
    while true
    do
        twotwo=$(panda $2)
        case "$1" in
            -a|--add)  add_option=1; bond_name=$twotwo; operate_type="add_bond"; shift ;;
            -t|--type) type_option=1; type_num=$twotwo; shift ;;
            -d|--delete) del_option=1; bond_name=$twotwo; operate_type="del_bond"; shift ;;
            -r|--remove) remove_option=1; shift ;;
            -u|--update) update_option=1; bond_name=$twotwo; operate_type="update_bond"; shift ;;
            -i|--info) info_option=1; bond_name=$twotwo; shift ;;
            -l|--log)  log_opt=1;
                case "$twotwo" in
                    "") log_file_name=${default_log_file}; ;;
                    *)  log_file_name=$twotwo; ;;
                esac
                shift ;;
            -v|--version) version; exit 1 ;;
            --author)  author; exit 1 ;;
            -h|--help)    usage_and_exit; exit 1 ;;
            -q) quit_option=1; exit 1 ;;
            --) shift; break ;;
            *) usage_and_exit; error "unsupport option, use -h to see more detail" ;;
        esac
        shift
    done
    interface_arr=(`echo $@ | xargs`)
    [[ -z "${bond_name}" ]] && error "must be known Bond Name is What? "
    if [ $quit_option -eq 1 ]; then
        exit 1
    fi
}

path=`dirname $0`
[[ "$path" = "." ]] && { path=`pwd` ; BASE_DIR=$path; cd $path; }
check_user_is_root
config_envir
arg_parse "$@"
judge_correct


printf "\033[34mPlease one moment, Bonding Tests are currently being executed.....\033[0m\n"
if [ $log_opt -eq 1 ]; then
    bonding_ROOT &> ${log_file_name}
else
    bonding_ROOT
fi


if [ $? -eq 0 ]; then
    success && printf "\033[5;34mBonding Tests\033[0m\n"
fi

clean_envir
